package com.frinder.official.akka.routing;

import akka.actor.*;
import akka.remote.routing.RemoteRouterConfig;
import akka.routing.*;
import com.frinder.official.spring.MyBaseActor;
import com.frinder.official.spring.SpringExtension;
import javafx.concurrent.Worker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * Created by frinder on 2017/9/29.
 */
@Component
@Scope("prototype")
public class PoolRouter extends MyBaseActor {

    @Autowired
    private SpringExtension springExtension;

    public void pool() {

        // create router by configuration(routing.conf)
        ActorRef router1 = getContext()
                .actorOf(FromConfig
                                .getInstance()
                                .props(springExtension.props("child")),
                        "router1");

        // create router by programmatically
        ActorRef router2 =
                getContext().actorOf(new RoundRobinPool(5)
                                .props(springExtension.props("child")),
                        "router2");

        // Remote Deployed Routees
        Address[] addresses = {
                new Address("akka.tcp", "remotesys", "otherhost", 1234),
                AddressFromURIString.parse("akka.tcp://othersys@anotherhost:1234")
        };
        ActorRef routerRemote = getContext().actorOf(
                new RemoteRouterConfig(new RoundRobinPool(5), addresses)
                        .props(springExtension.props("child"))
        );

        // Setting the strategy is easily done
        final SupervisorStrategy strategy =
                new OneForOneStrategy(
                        5,
                        Duration.create(1, TimeUnit.MINUTES),
                        Collections.singletonList(Exception.class)
                );
        final ActorRef router = getContext().actorOf(
                new RoundRobinPool(5)
                        .withSupervisorStrategy(strategy)
                        .props(springExtension.props("child"))
        );

        // Random pool by configuration
        ActorRef router5 =
                getContext().actorOf(
                        FromConfig
                                .getInstance()
                                .props(springExtension.props("child")),
                        "router5"
                );

        // Random pool by programmatically
        ActorRef router6 =
                getContext().actorOf(
                        new RandomPool(5)
                                .props(springExtension.props("child")),
                        "router6"
                );

        // BalancingPool defined in configuration:
        ActorRef router9 =
                getContext().actorOf(
                        FromConfig
                                .getInstance()
                                .props(springExtension.props("child")),
                        "router9"
                );

        // BalancingPool defined in code:
        ActorRef router10 =
                getContext().actorOf(
                        new BalancingPool(5)
                                .props(springExtension.props("child")),
                        "router10"
                );


        // SmallestMailboxPool defined in configuration:
        ActorRef router11 =
                getContext().actorOf(
                        FromConfig.getInstance()
                                .props(springExtension.props("child")),
                        "router11"
                );

        // SmallestMailboxPool defined in code:
        ActorRef router12 =
                getContext().actorOf(
                        new SmallestMailboxPool(5)
                                .props(springExtension.props("child")),
                        "router12"
                );


        // BroadcastPool defined in configuration:
        ActorRef router13 =
                getContext().actorOf(
                        FromConfig.getInstance().props(springExtension.props("child")),
                        "router13"
                );

        // BroadcastPool defined in code:
        ActorRef router14 =
                getContext().actorOf(
                        new BroadcastPool(5).props(springExtension.props("child")),
                        "router14"
                );


        // ScatterGatherFirstCompletedPool defined in configuration:
        ActorRef router17 =
                getContext().actorOf(
                        FromConfig.getInstance().props(springExtension.props("child")),
                        "router17"
                );

        // ScatterGatherFirstCompletedPool defined in code:
        FiniteDuration within = FiniteDuration.create(10, TimeUnit.SECONDS);
        ActorRef router18 =
                getContext().actorOf(
                        new ScatterGatherFirstCompletedPool(5, within)
                                .props(springExtension.props("child")),
                        "router18"
                );

        // TailChoppingPool defined in configuration:
        ActorRef router21 =
                getContext().actorOf(FromConfig.getInstance().props(
                        springExtension.props("child")), "router21");

        // TailChoppingPool defined in code:
        FiniteDuration within3 = FiniteDuration.create(10, TimeUnit.SECONDS);
        FiniteDuration interval = FiniteDuration.create(20, TimeUnit.MILLISECONDS);
        ActorRef router22 =
                getContext().actorOf(new TailChoppingPool(5, within3, interval).props(
                        Props.create(Worker.class)), "router22");


        // ConsistentHashingPool defined in configuration:
        ActorRef router25 =
                getContext().actorOf(FromConfig.getInstance().props(springExtension.props("child")),
                        "router25");

        // ConsistentHashingPool defined in code:
        ActorRef router26 =
                getContext().actorOf(new ConsistentHashingPool(5).props(
                        springExtension.props("child")), "router26");

    }


    @Override
    public Receive createReceive() {
        return null;
    }
}
